package com.ljx.itbbs.server.article.service.impl;

import cn.hutool.core.io.IoUtil;
import com.ljx.itbbs.common.manager.AsyncManager;
import com.ljx.itbbs.common.utils.AssertUtil;
import com.ljx.itbbs.oss.client.MinioTemplate;
import com.ljx.itbbs.server.article.dao.ResourceDao;
import com.ljx.itbbs.oss.domain.dto.MinioDownloadDto;
import com.ljx.itbbs.server.article.domain.entity.ResourceEntity;
import com.ljx.itbbs.server.article.domain.enums.ArticleResEnum;
import com.ljx.itbbs.server.article.domain.enums.ResourceFreeEnum;
import com.ljx.itbbs.server.article.domain.vo.req.ArticleResourceUploadReq;
import com.ljx.itbbs.server.article.service.ResourceService;
import com.ljx.itbbs.server.article.service.adapter.ArticleAdapter;
import com.ljx.itbbs.server.article.service.handler.ArticleAsyncHandler;
import com.ljx.itbbs.server.mall.domain.entity.OrderEntity;
import com.ljx.itbbs.server.mall.domain.enums.OrderTypeEnum;
import com.ljx.itbbs.server.mall.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;

@Slf4j
@Service
public class ResourceServiceImpl implements ResourceService {

    @Autowired
    private ResourceDao resourceDao;

    @Autowired
    private MinioTemplate minioTemplate;

    @Autowired
    private OrderService orderService;

    @Override
    public Long uploadArticleResource(Long userId, ArticleResourceUploadReq req) {
        ResourceEntity resourceEntity = ArticleAdapter.buildArticleResource(userId, req);
        resourceDao.save(resourceEntity);

        return resourceEntity.getId();
    }

    @Override
    public void batchUpdateResource(List<Long> resourcesList, Integer isFree, Integer integral, Long articleId) {
        resourceDao.batchUpdateResource(resourcesList, isFree, integral, articleId);
    }

    @Override
    public List<ResourceEntity> getByArticleId(Long articleId) {
        return resourceDao.getByArticleId(articleId);
    }

    @Override
    public void download(Long userId, Long resourceId, HttpServletResponse response) {
        // 查询是否收费
        ResourceEntity resource = resourceDao.getById(resourceId);
        if (resource.getIsFree().equals(ResourceFreeEnum.NOT_FREE.getType())){
            // 查询用户是否已经购买了该资源
            OrderEntity orderEntity = orderService.getOrder(userId, OrderTypeEnum.getObjId(resourceId, OrderTypeEnum.ARTICLE_RESOURCE));
            AssertUtil.isNotEmpty(orderEntity, "无权限下载");
        }
        // 获取资源输出流
        getResourceOutputStream(resource, response);
        // 异步更新下载次数
        AsyncManager.me().execute(ArticleAsyncHandler.increaseResourceDownloadNum(resource.getId()));
    }

    private void getResourceOutputStream(ResourceEntity resource, HttpServletResponse response) {
        MinioDownloadDto minioDownloadDto = minioTemplate.getDownloadDto(resource.getResUrl());
        try {
            InputStream inputStream = minioTemplate.getObject(minioDownloadDto.getBucket(), minioDownloadDto.getOssPath());
            // 设置下载文件的响应头
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=" + resource.getFilename());
            // 复制流
            IoUtil.copy(inputStream, response.getOutputStream(), IoUtil.DEFAULT_BUFFER_SIZE);
            // 关闭输入，输出流
            inputStream.close();
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void increaseDownloadNum(Long resourceId) {
        resourceDao.increaseDownloadNum(resourceId);
    }

    @Override
    public ResourceEntity getById(Long objId) {
        return resourceDao.getById(objId);
    }

    @Override
    public void deleteArticleResource(Long articleId) {
        resourceDao.deleteArticleResource(articleId);
    }

    @Override
    public void clearArticleId(Long articleId) {
        resourceDao.clearArticleId(articleId);
    }
}
